<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
    <title>Title</title>
    <style>
        video {
            width: 100%;
            max-width: 500px;
            display: block;
            border: 1px #000 solid;
        }
        pre {
            max-height: 200px;
            overflow: auto;
        }
    </style>
<!--    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>-->
</head>
<body>
<video controls id="video" webkit-playsinline="true" playsinline="true"></video>
频道ID：<input name="liveChannel"/>
<button id="start">开始</button>
<button id="stop">停止</button>
<button id="download">下载</button>
<pre></pre>
<script>
    const video = document.getElementById('video');
    const startBtn = document.getElementById('start');
    const stopBtn = document.getElementById('stop');
    const downloadBtn = document.getElementById('download');
    document.querySelector("input[name='liveChannel']").value = "live-" + Number(Math.random() * 100).toFixed(0);

    let socket;
    let recorder;
    let allChunks = [];
    function start() {
        let liveChannel = document.querySelector("input[name='liveChannel']").value;
        if(!liveChannel) {
            return;
        }
        socket = new WebSocket((location.protocol == "https:" ? "wss://" : "ws://") + location.host + "/video-transfer?liveChannel=" + liveChannel);
        //打开事件
        socket.onopen = function() {
            consolewrite("频道连接成功");
        };
        //获得消息事件
        socket.onmessage = function(msg) {
            let data = msg.data;
            if(data) {
                data = JSON.parse(data);
            }
            consolewrite("收到响应", msg.data)
            if(data.code == 0) {
                if(!navigator.mediaDevices) {
                    consolewrite("浏览器不支持");
                    socket.close()
                    return;
                }
                navigator.mediaDevices.getUserMedia({audio: true, video: true})
                    .then(stream => {
                        // 删除原来的blob
                        window.URL.revokeObjectURL(video.src);
                        video.srcObject = stream;
                        video.play();
                        allChunks = [];
                        recorder = new MediaRecorder(stream, {
                            audioBitsPerSecond : 128000,
                            videoBitsPerSecond : 2500000,
                            //mimeType : 'video/webm; codecs="h264"'
                            //mimeType : 'video/webm"'
                            mimeType : 'video/x-matroska;codecs=avc1,opus"'
                        });
                        recorder.ondataavailable = e => {
                            consolewrite("推送数据", {size: e.data.size, type: e.data.type});
                            //allChunks.push(e.data)
                            if(socket.readyState == WebSocket.OPEN) {
                                socket.send(e.data);
                            }
                            // e.data.arrayBuffer().then(buffer => {
                            //     if(socket.readyState == WebSocket.OPEN) {
                            //         socket.send(buffer);
                            //     }
                            // });
                        };
                        recorder.onstop = e => {
                            video.pause();
                            consolewrite("频道已关闭");
                        }
                        recorder.start(500);
                        consolewrite("频道开启成功");
                    }).catch(e => {
                        consolewrite("错误", e);
                    })
            }
        };
        //关闭事件
        socket.onclose = function() {
            recorder && recorder.stop();
            consolewrite("频道连接断开");
        };
        //发生了错误事件
        socket.onerror = function(e) {
            consolewrite("连接发生错误", e);
        }

    }

    function stop() {
        socket.close()
    }

    function download(){
        const fullBlob = new Blob(allChunks);
        const downloadUrl = window.URL.createObjectURL(fullBlob);
        const name = new Date().toISOString().slice(0,19).replace('T',' ').replace(' ','_').replace(/:/g,'-');
        const a = document.createElement('a');
        a.href = downloadUrl;
        a.download = `${name}.webm`;
        document.body.appendChild(a);
        a.click();
    }

    startBtn.addEventListener("click", start);
    stopBtn.addEventListener("click", stop);
    downloadBtn.addEventListener("click", download);

    function consolewrite() {
        document.querySelector("pre"). innerText += "\n" + Array.from(arguments).map(a => typeof(a) === "string" ? a : JSON.stringify(a)) .join(", ");
        document.querySelector("pre").scrollTop = 99999999999;
        console.log.apply(console, arguments)
    }
    /*
        const video = document.getElementById('video');
        const start = document.getElementById('start');
        const stop = document.getElementById('stop');
        const download = document.getElementById('download');


        const displayMediaOptions = {
            video: {
                cursor: "never"
            },
            audio: true
        }

        start.addEventListener('click',function(evt){
            startCapture();
        },false)

        stop.addEventListener('click',function(evt){
            stopCapture();
        },false)

        download.addEventListener('click',function(evt){
            mydownload();
        },false)


        let captureStream;
        let recorder;
        async function startCapture() {
            log = "";
            try {
                //captureStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
                captureStream = await navigator.mediaDevices.getUserMedia(displayMediaOptions);
            } catch (err) {
                consolewrite('Error: ' + err);
                return alert('capture is error or cancel!');
            }
            // 删除原来的blob
            window.URL.revokeObjectURL(video.src);
            video.srcObject = captureStream;
            //recorder = new MediaRecorder(captureStream);
            //recorder.start();

        }

        function stopCapture() {
            let tracks = video.srcObject.getTracks();
            tracks.forEach(track => {
                track.stop();
            });
            recorder.stop();
            recorder.addEventListener('dataavailable',(event)=>{
                let videoUrl = URL.createObjectURL(event.data,{type:'video/mp4'});
                video.srcObject = null;
                video.src = videoUrl;
            })

        }

        function mydownload(){
            const name = new Date().toISOString().slice(0,19).replace('T',' ').replace(' ','_').replace(/:/g,'-');
            const a = document.createElement('a');
            a.href = video.src;
            a.download = `${name}.mp4`;
            document.body.appendChild(a);
            a.click();

        }

        // 开始录制
        function startRecording() {
            var self = this;
            var constraints = {
                video: {
                    cursor: "never"
                }, // 视频信息的设置
                audio: true, // 是否包含音频信息
                logicalSurface: false, // 设置是否包含所选屏幕外区域的一些信息
            }
            navigator.mediaDevices.getDisplayMedia(constraints)
                .then(stream => {   //获取屏幕共享流
                    self.mediaStream = stream;
                    navigator.mediaDevices.getUserMedia({video: false, audio: true}).then(vstream => { // 获取音频流
                        self.recording = true;
                        self.index = 0;
                        self.chunks = []
                        // 音频/屏幕共享合并
                        vstream.getTracks().forEach(track => {
                            self.mediaStream_$
                            {
                                id
                            }
                        .
                            addTrack(track);
                        })
                        self.recorder = new MediaRecorder(stream);
                        self.recorder.ondataavailable = e => {
                            self.chunks.push(e.data)  // 存储所以的数据
                            if (!self.uploading) {
                                self.upload()
                            }
                        };
                        self.recorder.start(5000);  // 每5s执行一次dataavailable
                    })
                })
        }

        // 结束录制 同上

        // 上传
        function upload() {
            if (this.index > this.chunks.length) {
                // 存储的片段已全部上传
                this.uploading = false;
                return;
            }
            var fileName = ths.index + '.webm';
            var timestamp = (new Date()).valueOf();
            var suffix = getSuffix(fileName);
            var defaultDir = '/';
            // 文件名处理
            var fileInfo = {
                name: fileName,
                type: 'webm',
                size: file.size
            };
            var obj = {
                accessid: "*****"
                host: "******"
                policy: "*****"
                signature: "*****"
                expire: 16
                storeAs: "*****"
            }
            targetData = file,
                host = obj.host;
            var storeAs = obj.storeAs;
            var formData = new FormData();
            formData.append('key', storeAs);
            formData.append('policy', obj.policy);
            formData.append('OSSAccessKeyId', obj.accessid);
            formData.append('success_action_status', '200');
            formData.append('signature', obj.signature);
            formData.append('file', targetData, fileName);
            $.ajax({
                url: host,
                type: 'POST',
                data: formData,
                processData: false,
                contentType: false,
                success: () => {
                    fileInfo.url = host + storeAs
                    consolewrite('上传成功！！', fileInfo)
                    this.index++
                    this.upload()   // 递归，上传下一个片段
                },
                error: (XMLHttpRequest, textStatus, errorThrown) => {
                    console.error('上传失败')
                    this.uploading = flase;
                }
            })
        }

     */
</script>
</body>
</html>